home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
General
/
DR1.#1 PPC C⁄C++ ƒ
/
C++ Runtime ƒ
/
CPlusPlusLib.cp
next >
Wrap
Text File
|
1994-02-09
|
6KB
|
250 lines
/*
* CPlusLib.cp - C++ Runtime Support Routines for Metrowerks C++ (PowerPC)
*
* Copyright © 1993 metrowerks inc. All Rights Reserved.
*
*/
#include <stdlib.h>
/* private types */
typedef void (*ConstructorDestructor)(void *, int);
typedef struct DestructorChain {
struct DestructorChain *next; /* pointer to next destructor chain element */
ConstructorDestructor destructor; /* pointer to destructor function */
void *object; /* pointer to memory location (0L: element is marker) */
} DestructorChain;
typedef struct PTMF {
long this_delta; /* delta to this pointer */
long vtbl_offset; /* offset in vtable (-1: not a virtual function) */
union {
void *func_addr; /* nonvirtual function address */
long ventry_offset; /* offset of virtual function entry in vtable */
} func_data;
} PTMF;
/* private data */
static DestructorChain *__global_destructor_chain; /* chain of global objects that need destruction */
static DestructorChain *__local_destructor_chain; /* chain of local objects that need destruction */
/* prototypes */
extern "C" {
PTMF *__ptmf_cast(long offset, const PTMF *ptmfrom, PTMF *ptmto);
void *__register_global_object(void *object, ConstructorDestructor destructor, DestructorChain *regmem);
void *__register_local_object(void *object, ConstructorDestructor destructor, DestructorChain *regmem);
void __destroy_local_objects(DestructorChain *lastregmem);
void __destroy_local_chain(void);
void __destroy_global_chain(void);
void *__new_arr(ConstructorDestructor constructor, size_t objectsize, size_t nobjects);
void __del_arr(void *memptr, ConstructorDestructor destructor);
void __dc_arr(void *memptr, ConstructorDestructor constructordestructor, short objectsize, short nobjects);
}
/*
* __ptmf_cast - copy/cast a pointer-to-member-function
*
*/
PTMF *__ptmf_cast(long offset, const PTMF *ptmfrom, PTMF *ptmto)
{
ptmto->this_delta = ptmfrom->this_delta+offset;
if(ptmfrom->vtbl_offset >= 0L) { // virtual function pointer
ptmto->vtbl_offset = ptmfrom->vtbl_offset + offset;
ptmto->func_data.ventry_offset = ptmfrom->func_data.ventry_offset;
}
else { // nonvirtual function pointer
ptmto->vtbl_offset = -1L;
ptmto->func_data.func_addr = ptmfrom->func_data.func_addr;
}
return(ptmto);
}
/*
* __register_global_object - register a global object for later destruction
*
* We add the object and its destructor to a chain of (global object,destructor) pairs.
* The standard termination routine will traverse this list and destroy all objects
* whenever/however an application terminates.
*
*/
void *__register_global_object(void *object, ConstructorDestructor destructor, DestructorChain *regmem)
{
regmem->next = __global_destructor_chain;
regmem->destructor = destructor;
regmem->object = object;
__global_destructor_chain = regmem;
return(object);
}
/*
* __register_local_object - register a local object for later destruction
*
* We add the object and its destructor to a chain of (local object,destructor) pairs.
* These local objects are destroyed at the end of a scope or as part of stack unwinding
* when an exception is thrown.
*
*/
void *__register_local_object(void *object, ConstructorDestructor destructor, DestructorChain *regmem)
{
regmem->next = __local_destructor_chain;
regmem->destructor = destructor;
regmem->object = object;
__local_destructor_chain = regmem;
return(object);
}
/*
* __destroy_local_objects - destroy some local objects
*
* Call the destructor for every object in the local object chain up to (and
* including) 'lastregmem'.
*
*/
void __destroy_local_objects(DestructorChain *lastregmem)
{
DestructorChain *chain;
void *object;
while ((chain = __local_destructor_chain) != 0) {
if ((object = chain->object) != 0)
(*chain->destructor)(object, -1);
__local_destructor_chain = chain->next;
if (chain == lastregmem)
break;
}
}
/*
* __destroy_local_chain - destroy all local objects
*
* Call the destructor for every object in the local object chain.
*
*/
void __destroy_local_chain(void)
{
DestructorChain *chain;
void *object;
while ((chain = __local_destructor_chain) != 0) {
if ((object = chain->object) != 0)
(*chain->destructor)(object, -1);
__local_destructor_chain = chain->next;
}
}
/*
* __destroy_global_chain - destroy all global objects
*
* Call the destructor for every object in the global object chain.
*
*/
void __destroy_global_chain(void)
{
DestructorChain *chain;
void *object;
while ((chain = __global_destructor_chain) != 0) {
if ((object = chain->object) != 0)
(*chain->destructor)(object, -1);
__global_destructor_chain = chain->next;
}
}
/*
* __new_arr - allocate and construct an array of objects
*
* We allocate space for an array of 'nobjects' elements of size 'objectsize', and
* space to store 'nobjects' and 'objectsize' (for later deletion). Then we call
* the given constructor for each object in the array.
*
*/
void *__new_arr(ConstructorDestructor constructor, size_t objectsize, size_t nobjects)
{
char *memptr, *p;
if ((memptr = (char *) ::operator new(2*sizeof(size_t) + nobjects*objectsize)) != 0) {
memptr += 2*sizeof(size_t);
((size_t *) memptr)[-2] = objectsize;
((size_t *) memptr)[-1] = nobjects;
if (constructor) {
for (p = memptr; nobjects--; p += objectsize)
(*constructor)(p, 1);
}
}
return(memptr);
}
/*
* __del_arr - destroy and deallocate an array of objects
*
* We use the previously saved 'nobjects' and 'objectsize' values to call the
* destructor for each element of the array. Then we delete the space allocated
* to it.
*
*/
void __del_arr(void *memptr, ConstructorDestructor destructor)
{
size_t nobjects, objectsize;
char *p;
if (memptr) {
if (destructor) {
objectsize = ((size_t *) memptr)[-2];
nobjects = ((size_t *) memptr)[-1];
for (p = (char *) memptr; nobjects--; p += objectsize)
(*destructor)(p, -1);
}
::delete (&((size_t *) memptr)[-2]);
}
}
/*
* __dc_arr - construct or destroy a statically allocated array of objects
*
* We call the given constructor or destructor for each of 'nobjects' elements of size
* 'objectsize' in a statically allocated array.
*
*/
void __dc_arr(void *memptr, ConstructorDestructor constructordestructor, short objectsize, short nobjects)
{
char *p;
for (p = (char *) memptr; nobjects--; p += objectsize)
(*constructordestructor)(p, -1);
}